package com.imut.lagain.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.imut.lagain.entity.Message;
import com.imut.lagain.repository.MessageRepository;
import com.imut.lagain.service.MessageService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;

/**
 * 消息服务实现类
 */
@Service
public class MessageServiceImpl implements MessageService {
    private static final Logger log = LoggerFactory.getLogger(MessageServiceImpl.class);
    
    @Autowired
    private MessageRepository messageRepository;
    
    // 消息发送频率限制（每分钟最多发送消息数）
    private static final int RATE_LIMIT_PER_MINUTE = 60;
    
    // 消息撤回时间限制（分钟）
    private static final int RECALL_TIME_LIMIT = 2;
    
    @Override
    @Transactional
    public Message sendMessage(Long senderId, Long receiverId, String messageType, 
                              String content, String mediaUrl) {
        log.info("发送消息: senderId={}, receiverId={}, type={}", senderId, receiverId, messageType);
        
        // 检查发送频率限制
        if (!checkRateLimit(senderId)) {
            throw new RuntimeException("发送消息过于频繁，请稍后再试");
        }
        
        Message message = new Message();
        message.setSenderId(senderId);
        message.setReceiverId(receiverId);
        message.setMessageType(messageType);
        message.setContent(content);
        message.setMediaUrl(mediaUrl);
        message.setStatus(Message.STATUS_SENT);
        message.setCreateTime(LocalDateTime.now());
        
        messageRepository.insert(message);
        
        // TODO: 发送WebSocket实时通知
        
        return message;
    }
    
    @Override
    public Message sendTextMessage(Long senderId, Long receiverId, String content) {
        return sendMessage(senderId, receiverId, Message.TYPE_TEXT, content, null);
    }
    
    @Override
    public Message sendImageMessage(Long senderId, Long receiverId, String imageUrl) {
        return sendMessage(senderId, receiverId, Message.TYPE_IMAGE, "[图片]", imageUrl);
    }
    
    @Override
    public Message sendAudioMessage(Long senderId, Long receiverId, String audioUrl) {
        return sendMessage(senderId, receiverId, Message.TYPE_AUDIO, "[语音]", audioUrl);
    }
    
    @Override
    public Message sendSystemMessage(Long receiverId, String content, String extraData) {
        Message message = new Message();
        message.setSenderId(0L); // 系统消息发送者ID为0
        message.setReceiverId(receiverId);
        message.setMessageType(Message.TYPE_SYSTEM);
        message.setContent(content);
        message.setExtraData(extraData);
        message.setStatus(Message.STATUS_SENT);
        message.setCreateTime(LocalDateTime.now());
        
        messageRepository.insert(message);
        return message;
    }
    
    @Override
    public Message replyMessage(Long senderId, Long receiverId, String content, 
                               Long replyToId, String messageType) {
        Message message = new Message();
        message.setSenderId(senderId);
        message.setReceiverId(receiverId);
        message.setMessageType(messageType);
        message.setContent(content);
        message.setReplyToId(replyToId);
        message.setStatus(Message.STATUS_SENT);
        message.setCreateTime(LocalDateTime.now());
        
        messageRepository.insert(message);
        return message;
    }
    
    @Override
    public IPage<Message> getChatHistory(Long userId1, Long userId2, int page, int size) {
        Page<Message> pageParam = new Page<>(page, size);
        return messageRepository.findChatHistory(pageParam, userId1, userId2);
    }
    
    @Override
    public List<Map<String, Object>> getChatPartners(Long userId) {
        List<Object> partners = messageRepository.findChatPartners(userId);
        List<Map<String, Object>> result = new ArrayList<>();
        
        for (Object partner : partners) {
            if (partner instanceof Map) {
                result.add((Map<String, Object>) partner);
            }
        }
        
        return result;
    }
    
    @Override
    public Message getLatestMessage(Long userId1, Long userId2) {
        return messageRepository.findLatestMessage(userId1, userId2);
    }
    
    @Override
    public Long getUnreadMessageCount(Long userId) {
        return messageRepository.countUnreadMessages(userId);
    }
    
    @Override
    public Long getUnreadMessageCountBetween(Long senderId, Long receiverId) {
        return messageRepository.countUnreadMessagesBetween(senderId, receiverId);
    }
    
    @Override
    @Transactional
    public boolean markAsRead(Long messageId, Long userId) {
        Message message = messageRepository.selectById(messageId);
        if (message == null || !message.getReceiverId().equals(userId)) {
            return false;
        }
        
        int result = messageRepository.markAsRead(messageId, LocalDateTime.now());
        return result > 0;
    }
    
    @Override
    @Transactional
    public boolean markAllAsReadBetween(Long senderId, Long receiverId) {
        int result = messageRepository.markAllAsReadBetween(senderId, receiverId, LocalDateTime.now());
        return result >= 0;
    }
    
    @Override
    @Transactional
    public boolean deleteMessage(Long messageId, Long userId) {
        Message message = messageRepository.selectById(messageId);
        if (message == null || (!message.getSenderId().equals(userId) && !message.getReceiverId().equals(userId))) {
            return false;
        }
        
        message.setIsDeleted(true);
        int result = messageRepository.updateById(message);
        return result > 0;
    }
    
    @Override
    @Transactional
    public boolean recallMessage(Long messageId, Long userId) {
        Message message = messageRepository.selectById(messageId);
        if (message == null || !message.getSenderId().equals(userId)) {
            return false;
        }
        
        // 检查撤回时间限制
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime createTime = message.getCreateTime();
        if (createTime.plusMinutes(RECALL_TIME_LIMIT).isBefore(now)) {
            throw new RuntimeException("消息发送超过" + RECALL_TIME_LIMIT + "分钟，无法撤回");
        }
        
        message.setContent("[消息已撤回]");
        message.setMediaUrl(null);
        message.setUpdateTime(now);
        
        int result = messageRepository.updateById(message);
        return result > 0;
    }
    
    @Override
    public List<Message> getMessagesByTimeRange(Long userId1, Long userId2, 
                                               LocalDateTime startTime, LocalDateTime endTime) {
        return messageRepository.findMessagesByTimeRange(userId1, userId2, startTime, endTime);
    }
    
    @Override
    public List<Message> searchMessages(Long userId1, Long userId2, String keyword) {
        return messageRepository.searchMessages(userId1, userId2, keyword);
    }
    
    @Override
    public IPage<Message> getSystemMessages(Long userId, int page, int size) {
        Page<Message> pageParam = new Page<>(page, size);
        return messageRepository.findSystemMessages(pageParam, userId);
    }
    
    @Override
    public Message getMessageById(Long messageId, Long userId) {
        Message message = messageRepository.selectById(messageId);
        if (message == null || !hasPermission(messageId, userId)) {
            return null;
        }
        return message;
    }
    
    @Override
    @Transactional
    public boolean updateMessageStatus(Long messageId, String status) {
        Message message = messageRepository.selectById(messageId);
        if (message == null) {
            return false;
        }
        
        message.setStatus(status);
        message.setUpdateTime(LocalDateTime.now());
        
        int result = messageRepository.updateById(message);
        return result > 0;
    }
    
    @Override
    public Map<String, Object> getMessageStatistics(Long userId) {
        Map<String, Object> stats = new HashMap<>();
        
        // 总消息数
        Long totalSent = messageRepository.selectCount(
            new LambdaQueryWrapper<Message>().eq(Message::getSenderId, userId));
        Long totalReceived = messageRepository.selectCount(
            new LambdaQueryWrapper<Message>().eq(Message::getReceiverId, userId));
        
        // 未读消息数
        Long unreadCount = getUnreadMessageCount(userId);
        
        // 今日消息数
        Long todayCount = getTodayMessageCount(userId);
        
        stats.put("totalSent", totalSent);
        stats.put("totalReceived", totalReceived);
        stats.put("unreadCount", unreadCount);
        stats.put("todayCount", todayCount);
        
        return stats;
    }
    
    @Override
    @Transactional
    public int cleanExpiredMessages(int days) {
        LocalDateTime expireTime = LocalDateTime.now().minusDays(days);
        return messageRepository.deleteExpiredMessages(expireTime);
    }
    
    @Override
    public boolean hasPermission(Long messageId, Long userId) {
        Message message = messageRepository.selectById(messageId);
        if (message == null) {
            return false;
        }
        
        return message.getSenderId().equals(userId) || message.getReceiverId().equals(userId);
    }
    
    @Override
    public List<Message> getMessageReplies(Long messageId) {
        return messageRepository.selectList(
            new LambdaQueryWrapper<Message>()
                .eq(Message::getReplyToId, messageId)
                .orderByAsc(Message::getCreateTime));
    }
    
    @Override
    @Transactional
    public Message forwardMessage(Long messageId, Long senderId, Long receiverId) {
        Message originalMessage = messageRepository.selectById(messageId);
        if (originalMessage == null || !hasPermission(messageId, senderId)) {
            throw new RuntimeException("无权限转发此消息");
        }
        
        Message forwardMessage = new Message();
        forwardMessage.setSenderId(senderId);
        forwardMessage.setReceiverId(receiverId);
        forwardMessage.setMessageType(originalMessage.getMessageType());
        forwardMessage.setContent("[转发] " + originalMessage.getContent());
        forwardMessage.setMediaUrl(originalMessage.getMediaUrl());
        forwardMessage.setStatus(Message.STATUS_SENT);
        forwardMessage.setCreateTime(LocalDateTime.now());
        
        messageRepository.insert(forwardMessage);
        return forwardMessage;
    }
    
    @Override
    public Long getTodayMessageCount(Long userId) {
        LocalDateTime startOfDay = LocalDateTime.now().withHour(0).withMinute(0).withSecond(0).withNano(0);
        LocalDateTime endOfDay = startOfDay.plusDays(1);
        
        return messageRepository.selectCount(
            new LambdaQueryWrapper<Message>()
                .eq(Message::getSenderId, userId)
                .between(Message::getCreateTime, startOfDay, endOfDay));
    }
    
    @Override
    public boolean checkRateLimit(Long userId) {
        LocalDateTime oneMinuteAgo = LocalDateTime.now().minusMinutes(1);
        
        Long recentMessageCount = messageRepository.selectCount(
            new LambdaQueryWrapper<Message>()
                .eq(Message::getSenderId, userId)
                .gt(Message::getCreateTime, oneMinuteAgo));
        
        return recentMessageCount < RATE_LIMIT_PER_MINUTE;
    }
}